package top.zaixia.game.util.bean

import io.jsonwebtoken.Jwts
import io.jsonwebtoken.SignatureAlgorithm
import io.jsonwebtoken.security.Keys
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.context.properties.bind.ConstructorBinding
import java.security.Key
import java.util.*

@ConfigurationProperties(prefix = "app.jwt")
class JwtUtil
@ConstructorBinding constructor(
  val issuer: String,
  val secret: String,
  val duration: Long,
) {
	/**
	 * 生成 token
	 * @param userId 用户 id
	 * @return token
	 */
	fun getToken(userId: String): String {
		val expirationDate = Date(System.currentTimeMillis() + duration)
		
		return Jwts.builder()
		  .setIssuer(issuer)       // 签发者
		  .setSubject(userId)     // 主题
		  .setIssuedAt(Date())        // 签发时间
		  .setExpiration(expirationDate) // 过期时间
		  .signWith(getSigningKey(), getSign()) // 签名算法
		  .compact()
	}
	
	/**
	 * 解析 token
	 * @param token token
	 * @return 用户 id
	 */
	fun parseToken(token: String) = try {
		Jwts.parserBuilder()
		  .setSigningKey(getSigningKey())
		  .build()
		  .parseClaimsJws(token)
		  .body
		  .subject
	} catch (_: Exception) {
		null
	}
	
	/**
	 * 验证 token
	 * @param token token
	 * @return 是否有效
	 */
	fun isValid(token: String) = try {
		parseToken(token) != null
	} catch (_: Exception) {
		false
	}
	
	/* 用 secret 生成签名 key */
	private fun getSigningKey(): Key {
		return Keys.hmacShaKeyFor(secret.toByteArray())
	}
	
	/* 编码格式 */
	private fun getSign(): SignatureAlgorithm {
		return SignatureAlgorithm.HS256
	}
}